<?php

vendor('abstract_object');

class Date extends AbstractObject
{
    protected $timestamp;

    static function Human($timestamp, $time=true)
    {
        $result = '';
        $now = time();
        if (date('Y-m-d', $timestamp) != date('Y-m-d', $now)) {
            $result .= date('d', $timestamp);
            $result .= ' ';
            $result .= mb_convert_case(self::ru_month2(intval(date('m', $timestamp))), MB_CASE_LOWER, DEFAULT_CHARSET);
            if (date('Y', $timestamp) != date('Y', $now)) {
                $result .= ' ';
                $result .= date('Y', $timestamp);
            }

            if ($time) {
                $result .= ' '.__d(null, 'in_time', true).' ';
            }
        }

        if ($time) {
            $result .= date('H:i', $timestamp);
        }

        return $result;
    }

    static function Full($timestamp, $time=true)
    {
        $result = '';
        $result .= date('d', $timestamp);
        $result .= ' ';
        $result .= mb_convert_case(self::ru_month2(intval(date('m', $timestamp))), MB_CASE_LOWER, DEFAULT_CHARSET);
        $result .= ' ';
        $result .= date('Y', $timestamp);
        if ($time) {
            $result .= ' '.__d(null, 'in_time', true).' ';
            $result .= date('H:i', $timestamp);
        }

        return $result;
    }

    static function Short($timestamp, $time=true)
    {
        if ($time) {
            return date('d.m.y H:i', $timestamp);
        } else {
            return date('d.m.y', $timestamp);
        }
    }

    static function ru_month($month)
    {

        $months = array(
             1 => __d('dates', 'month_january', true),
             2 => __d('dates', 'month_february', true),
             3 => __d('dates', 'month_march', true),
             4 => __d('dates', 'month_april', true),
             5 => __d('dates', 'month_may', true),
             6 => __d('dates', 'month_june', true),
             7 => __d('dates', 'month_july', true),
             8 => __d('dates', 'month_august', true),
             9 => __d('dates', 'month_september', true),
            10 => __d('dates', 'month_october', true),
            11 => __d('dates', 'month_november', true),
            12 => __d('dates', 'month_december', true),
        );
        return $months[$month];
    }

    static function ru_month2($month)
    {
        $months = array(
             1 => __d('dates', 'month2_january', true),
             2 => __d('dates', 'month2_february', true),
             3 => __d('dates', 'month2_march', true),
             4 => __d('dates', 'month2_april', true),
             5 => __d('dates', 'month2_may', true),
             6 => __d('dates', 'month2_june', true),
             7 => __d('dates', 'month2_july', true),
             8 => __d('dates', 'month2_august', true),
             9 => __d('dates', 'month2_september', true),
            10 => __d('dates', 'month2_october', true),
            11 => __d('dates', 'month2_november', true),
            12 => __d('dates', 'month2_december', true),
        );
        return $months[$month];
    }

    static function ru_month_short($month)
    {
        $months = array(
             1 => __d('dates', 'month_short_january', true),
             2 => __d('dates', 'month_short_february', true),
             3 => __d('dates', 'month_short_march', true),
             4 => __d('dates', 'month_short_april', true),
             5 => __d('dates', 'month_short_may', true),
             6 => __d('dates', 'month_short_june', true),
             7 => __d('dates', 'month_short_july', true),
             8 => __d('dates', 'month_short_august', true),
             9 => __d('dates', 'month_short_september', true),
            10 => __d('dates', 'month_short_october', true),
            11 => __d('dates', 'month_short_november', true),
            12 => __d('dates', 'month_short_december', true),
        );
        return $months[$month];
    }

    static function getTimeFromComaTime($str)
    {
        $ar = explode(':', $str);
        $result = 0;
        $result += (isset($ar[0]) ? intval(trim($ar[0])) : 0)*3600;
        $result += (isset($ar[1]) ? intval(trim($ar[1])) : 0)*60;
        $result += (isset($ar[2]) ? intval(trim($ar[2])) : 0);
        return $result;
    }

    static function HumanPass($diff)
    {
        if ($diff < 60) {
            return 'только что';
        } elseif ($diff < 3600*24) {
            return self::_hoursPass($diff);
        } elseif ($diff < 3600*24*7) {
            return 'много';
        }
    }

    static function _hoursPass($diff)
    {
        $hours = (int)floor(($diff % (24*3600))/3600);

        $precision = 0;
        if ($hours <= 5) {
            $precision = 3;
        } elseif ($hours <= 12) {
            $precision = 1;
        }
        $add = 0;
        $suff = self::_hourPart($diff, $precision, $add);

        $hours += $add;

        return $hours.$suff;
    }

    static function _hourPart($diff, $precision, &$add)
    {
        /**
         * &#188; -- 1/4
         * &#189; -- 1/2
         * &#190; -- 3/4
         * &#8531; -- 1/3
         * &#8532; -- 2/3
         */

        $hour_part = ($diff % 3600)/3600;

        $add = 0;
        switch ($precision) {
        case 0:
            $res = (int)round($hour_part);
            switch ($res) {
            case 0:
                return '';

            case 1:
                $add = 1;
                return '';
            }

        case 1:
            $res = (int)round($hour_part*2);
            switch ($res) {
            case 0:
                return '';

            case 1:
                return '½';

            case 2:
                $add = 1;
                return '';

            }

        case 2:
            $res = (int)round($hour_part*3);
            switch ($res) {
            case 0:
                return '';

            case 1:
                return '⅓';

            case 2:
                return '⅔';

            case 3:
                $add = 1;
                return '';
            }

        case 3:
            $res = (int)round($hour_part*4);
            switch ($res) {
            case 0:
                return '';

            case 1:
                return '¼';

            case 2:
                return '½';

            case 3:
                return '¾';

            case 4:
                $add = 1;
                return '';
            }
        }
    }

    static function SQL2UNIX($date)
    {
        $year   = intval(substr($date, 0, 4));
        $mon    = intval(substr($date, 5, 2));
        $day    = intval(substr($date, 8, 2));
        $hour   = intval(substr($date, 11, 2));
        $min    = intval(substr($date, 14, 2));
        $sec    = intval(substr($date, 17, 2));

        return mktime($hour, $min, $sec, $mon, $day, $year);
    }

    static function getDaysNumInMonth($mon, $year)
    {
        if (!is_int($mon) || !is_int($year) || !($mon >= 1 && $mon <= 12)) {
            throw new ArgException();
        }
        return intval(date('t', mktime(0, 0, 0, $mon, 1, $year)));
    }

    static function getEndParsedDateFromNotFull($date)
    {
        switch (count($date)) {
        case 1:
            $date['mon'] = 12;
        case 2:
            $date['day'] = self::getDaysNumInMonth($date['mon'], $date['year']);
        case 3:
            $date['hour'] = 23;
        case 4:
            $date['min'] = 59;
        case 5:
            $date['sec'] = 59;
        case 6:
            break;

        default:
            throw new ArgException();
        }

        return $date;
    }

    static function getBeginParsedDateFromNotFull($date)
    {
        switch (count($date)) {
        case 1:
            $date['mon'] = 1;
        case 2:
            $date['day'] = 1;
        case 3:
            $date['hour'] = 0;
        case 4:
            $date['min'] = 0;
        case 5:
            $date['sec'] = 0;
        case 6:
            break;

        default:
            throw new ArgException();
        }

        return $date;
    }

    static function getUnixFromFullParsed($date)
    {
        return mktime($date["hour"], $date["min"], $date["sec"], $date["mon"], $date["day"], $date["year"]);
    }

    static function Unix2SQL($timestamp)
    {
        return date('Y-m-d H:i:s', $timestamp);
    }

    static function parseSQLDateTime($data)
    {
        $valid = true;

        if (preg_match('/^(\\d{4})(?:-(\\d{2})(?:-(\\d{2})(?: (\\d{2})(?::(\\d{2})(?::(\\d{2}))?)?)?)?)?$/s', $data, $matches)) {
            $result = array();
            $result['year'] = intval($matches[1]);
            if (isset($matches[2])) {
                $value = intval($matches[2]);
                if ($value >= 1 && $value <= 12) {
                    $result['mon'] = $value;
                    if (isset($matches[3])) {
                        $value = intval($matches[3]);
                        if ($value >= 1 && $value <= self::getDaysNumInMonth($result['mon'], $result['year'])) {
                            $result['day'] = $value;
                            if (isset($matches[4])) {
                                $value = intval($matches[4]);
                                if ($value <= 23) {
                                    $result['hour'] = $value;
                                    if (isset($matches[5])) {
                                        $value = intval($matches[5]);
                                        if ($value <= 59) {
                                            $result['min'] = $value;
                                            if (isset($matches[6])) {
                                                $value = intval($matches[6]);
                                                if ($value <= 59) {
                                                    $result['sec'] = $value;
                                                } else {
                                                    $valid = false;
                                                }
                                            }
                                        } else {
                                            $valid = false;
                                        }

                                    }
                                } else {
                                    $valid = false;
                                }
                            }
                        } else {
                            $valid = false;
                        }
                    }
                } else {
                    $valid = false;
                }
            }
        } else {
            $valid = false;
        }

        if (! $valid) {
            throw new ArgException("Incorrect SQL date: '{$data}'");
        }

        return $result;
    }

    static function SQLEndDatetime($sql_datetime)
    {
        return self::Unix2SQL(self::getUnixFromFullParsed(self::getEndParsedDateFromNotFull(self::parseSQLDateTime($sql_datetime))));
    }

    static function SQLBeginDatetime($sql_datetime)
    {
        return self::Unix2SQL(self::getUnixFromFullParsed(self::getBeginParsedDateFromNotFull(self::parseSQLDateTime($sql_datetime))));
    }
    /**
     * Returns a datetime for the end date of a period
     *
     * @param string $date
     * @return string
     */
    static function getEndDateTime4Date($date)
    {
        $dateTime = $date;
    	if(strlen($date) <= 10)
    	{
    		$dateTime = date("Y-m-d", strtotime($date))." 23:59:59";
    	}
    	return $dateTime;
    }

    /**
     * deprecated
     */
    static function getToDateTime($date)
    {
    	return self::SQLEndDatetime($date);
    }

    static function valid_sql_date($str)
    {
        if (mb_ereg('^(\\d{4}).(\\d{2}).(\\d{2})$', $str, $matches)) {
            return self::valid(intval($matches[1]), intval($matches[2]), intval($matches[3]));
        }
        return false;
    }

    static function valid_sql_datetime($str)
    {
        if (mb_ereg('^(\\d{4}).(\\d{2}).(\\d{2}).(\\d{2}).(\\d{2}).(\\d{2})$', $str, $matches)) {
            return self::valid(intval($matches[1]), intval($matches[2]), intval($matches[3]), intval($matches[4]), intval($matches[5]), intval($matches[6]));
        }
        return false;
    }

    static function valid($year, $month = 1, $days = 1, $hours = 0, $minutes = 0, $seconds = 0)
    {
        $vs = array(&$year, &$month, &$days, &$hours, &$minutes, &$seconds);
        $c_vs = count($vs);
        for ($i = 0; $i < $c_vs; $i++) {
            if (! is_int($vs[$i])) {
                return false;
            }
        }
        $max_days = $month==2 ? (self::leap_year($year)?29:28) : (self::big_month($month)?31:30);
        if (
            $month >= 1 &&
            $month <= 12 &&
            $days >= 1 &&
            $days <= $max_days &&
            $hours >= 0 &&
            $hours <= 23 &&
            $minutes >= 0 &&
            $minutes <= 59 &&
            $seconds >= 0 &&
            $seconds <= 59
        ) {
            return true;
        }
        return false;
    }

    static function valid_res_year($year, $month = 1, $days = 1, $hours = 0, $minutes = 0, $seconds = 0)
    {
        return
            $year >= 1000 && // For MySQL
            $year <= 9999 && // For MySQL
            self::valid($year, $month, $days, $hours, $minutes, $seconds);
    }

    static function leap_year($y)
    {
        return $y%100 ? !(bool)($y%4) : !(bool)($y%400);
    }

    static function big_month($m)
    {
        return (bool)(($m+(int)($m>7))%2);
    }

}

/**
 * Класс работы с датой и временем по григорианскому календарю и UTC.
 *
 */
class Datetime2 extends AbstractObject
{
    protected $timestamp = null;

    function dayOfWeek($year, $month, $day)
    {
        $a = (14 - $month)/12;
        $y = $year + 4800 - $a;
        $m = $month + 12*$a - 3;
        $Date = $day + (153*$m + 2)/5 + 365*$y + $y/4 - $y/100 + $y/400 - 32045;
        $day_of_week = $Date % 7 + 1;

        return $day_of_week;
    }
}



?>